﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Web.Mvc;
using System.Reflection;
using System.IO;
using System.Web.Mvc.Html;
using MvcControlsToolkit;


namespace MvcControlsToolkit
{
    public static class ControlManager
    {
        public static MvcHtmlString Plot(this HtmlHelper html, Plot plot)
        {
            ScriptManager.AddReferenceToFile("jquery-ui-1.8.11.min.js", "script");
            ScriptManager.AddReferenceToFile("jquery.jqplot.js", "script");
            ScriptManager.AddReferenceToFile("jquery.jqplot.min.css", "css");
            ScriptManager.AddReferenceToFile("jquery.ui.all.css", "css");

            plot.Helper = html;
            ScriptManager.InnerScript(plot.GetJScript());
            return new MvcHtmlString(plot.GetHtml());
        }
        /// <summary>
        /// Creates a DatePicker for the current fie
        /// NOTE: the element must contain an id in the following format: id="THE-ELEMENT-ID"
        /// </summary>
        /// <param name="html"></param>
        /// <param name="datePicker"></param>
        /// <returns></returns>
        public static MvcHtmlString AutoComplete(this HtmlHelper html, AutoComplete autoComplete)
        {
            ScriptManager.AddReferenceToFile("jquery-ui-1.8.11.min.js", "script");
            ScriptManager.AddReferenceToFile("jquery.ui.autocomplete.css", "css");

            autoComplete.Helper = html;
            ScriptManager.InnerScript(autoComplete.GetJScript());
            return new MvcHtmlString(autoComplete.GetHtml());
        }

        public static MvcHtmlString Splitter(this HtmlHelper html, Splitter splitter)
        {
            ScriptManager.AddReferenceToFile("jquery-ui-1.8.11.min.js", "script");
            ScriptManager.AddReferenceToFile("jquery-splitter.js", "script");
            ScriptManager.AddReferenceToFile("jquery.splitter.css", "css");

            splitter.Helper = html;
            ScriptManager.InnerScript(splitter.GetJScript());
            return new MvcHtmlString(splitter.GetHtml());
        }

        /// <summary>
        /// Creates a DatePicker for the current fie
        /// NOTE: the element must contain an id in the following format: id="THE-ELEMENT-ID"
        /// </summary>
        /// <param name="html"></param>
        /// <param name="datePicker"></param>
        /// <returns></returns>
        public static MvcHtmlString DatePicker(this HtmlHelper html, DatePicker datePicker)
        {
            ScriptManager.AddReferenceToFile("jquery-ui-1.8.11.min.js", "script");
            ScriptManager.AddReferenceToFile("jquery.ui.datepicker.css", "css");            

            datePicker.Helper = html;
            ScriptManager.InnerScript(datePicker.GetJScript());
            return new MvcHtmlString(datePicker.GetHtml());
        }

        public static MvcHtmlString Accordion(this HtmlHelper html, Accordion accordian)
        {
            ScriptManager.AddReferenceToFile("jquery-ui-1.8.11.min.js", "script");
            ScriptManager.AddReferenceToFile("jquery.ui.accordion.css", "css");

            accordian.Helper = html;
            ScriptManager.InnerScript(accordian.GetJScript());
            return new MvcHtmlString(accordian.GetHtml());
        }

        public static MvcHtmlString Tabs(this HtmlHelper html, Tabs tabs)
        {
            ScriptManager.AddReferenceToFile("jquery-ui-1.8.11.min.js", "script");
            ScriptManager.AddReferenceToFile("jquery.ui.tabs.css", "css");

            tabs.Helper = html;
            ScriptManager.InnerScript(tabs.GetJScript());
            return new MvcHtmlString(tabs.GetHtml());
        }

        public static MvcHtmlString Progressbar(this HtmlHelper html, ProgressBar progressbar)
        {
            ScriptManager.AddReferenceToFile("jquery-ui-1.8.11.min.js", "script");
            ScriptManager.AddReferenceToFile("jquery.ui.progressbar.css", "css");

            progressbar.Helper = html;
            ScriptManager.InnerScript(progressbar.GetJScript());
            return new MvcHtmlString(progressbar.GetHtml());
        }

        public static MvcHtmlString Slider(this HtmlHelper html, Slider slider)
        {
            ScriptManager.AddReferenceToFile("jquery-ui-1.8.11.min.js", "script");
            ScriptManager.AddReferenceToFile("jquery.ui.slider.css", "css");

            slider.Helper = html;

            ScriptManager.InnerScript(slider.GetJScript());
            return new MvcHtmlString(slider.GetHtml());
        }

        public static MvcHtmlString Window(this HtmlHelper html, Window window)
        {
            ScriptManager.AddReferenceToFile("jquery-ui-1.8.11.min.js", "script");
            ScriptManager.AddReferenceToFile("jquery.ui.dialog.css", "css");

            window.Helper = html;
            ScriptManager.InnerScript(window.GetJScript());
            return new MvcHtmlString(window.GetHtml());
        }

        /// <summary>
        /// Serializes the specified model object to a GET querystring parameter
        /// Note: The serialization is shallow, meaning only first level properties are serialized
        /// </summary>
        /// <param name="html"></param>
        /// <param name="model">The model object to serialize</param>
        /// <param name="parameterName">The parameter name of the Controller method</param>
        /// <returns></returns>
        public static string BuildQuery(this HtmlHelper html, object model, string parameterName)
        {

            PropertyInfo[] props = model.GetType().GetProperties();
            StringBuilder sb = new StringBuilder();
            sb.Append("?");
            bool isFirst = true;

            foreach (PropertyInfo prop in props)
            {
                object val = prop.GetValue(model, null);
                if (val != null)
                {
                    if (isFirst) isFirst = false;
                    else sb.Append("&");
                    sb.AppendFormat("{0}.{1}={2}", parameterName, prop.Name, val);
                }
            }

            return sb.ToString();
        }

        private static string getIdFromString(MvcHtmlString html)
        {
            string raw = html.ToHtmlString();
            if (raw.IndexOf("id=") == -1)
                throw new ArgumentException("MVC.Controls.DatePicker can only be used for MvcHtmlString with an html-id"
                    + Environment.NewLine + "[" + html.ToHtmlString() + "]");

            raw = raw.Substring(raw.IndexOf("id=") + 4);
            raw = raw.Substring(0, raw.IndexOf("\""));

            return raw;
        }

        internal static string RenderPartialToString(HtmlHelper htmlHelper, string viewName, object viewModel, ViewDataDictionary viewData)
        {
            var sw = new StringWriter();

            var newViewContext = new ViewContext(htmlHelper.ViewContext.Controller.ControllerContext,
                                                         new FakeView(),
                                                         htmlHelper.ViewContext.ViewData,
                                                         htmlHelper.ViewContext.TempData,
                                                         sw);

            var newHelper = new HtmlHelper(newViewContext, new ViewPage());
            newHelper.RenderPartial(viewName, viewModel, viewData);

            var res = sw.ToString();
            sw.Close();
            sw.Dispose();

            return res;
        }
    }

    internal class FakeView : IView
    {
        public void Render(ViewContext viewContext, TextWriter writer)
        {
            throw new NotImplementedException();
        }
    }
}

